package com.koro.controller;


import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;
import org.springframework.ai.openai.*;
import org.springframework.ai.openai.api.OpenAiAudioApi;
import org.springframework.ai.openai.api.OpenAiImageApi;
import org.springframework.ai.openai.audio.speech.SpeechPrompt;
import org.springframework.ai.openai.audio.speech.SpeechResponse;
import org.springframework.ai.openai.audio.transcription.AudioTranscriptionPrompt;
import org.springframework.ai.openai.audio.transcription.AudioTranscriptionResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.io.FileOutputStream;


@Tag(name = "openAi demo")
@RestController
@RequestMapping("/ai")
public class ChatController {

    /**
     * 通用客户端，可以切换不同大模型都可以使用，但对于大模型特有的性能无法支持。需要自定义bean
     */
    @Autowired
    private ChatClient chatClient;
    /**
     * 独有客户端，在start自动装配类中
     */
    @Autowired
    private ChatModel chatModel;

    @Autowired
    private OpenAiImageModel openAiImageModel;

    @Autowired
    private OpenAiAudioSpeechModel openAiAudioSpeechModel;

    @Autowired
    private OpenAiAudioTranscriptionModel openAiAudioTranscriptionModel;


    @GetMapping("/chat")
    @Operation(summary = "智能问答")
    public String generation(@RequestParam(value = "message",defaultValue = "给我讲个笑话")String message) {
        // prompt: 提示词
        return this.chatClient.prompt()
                // 用户信息
                .user(message)
                // 远程请求大模型
                .call()
                // 返回文本
                .content();
    }

    /**
     * 流式响应
     * @param message
     * @return
     */
    @GetMapping(value = "/stream",produces = "text/html;charset=UTF-8")
    @Operation(summary = "流式智能问答")
    public Flux<String> stream(@RequestParam(value = "message",defaultValue = "给我讲个笑话")String message) {
        Flux<String> output = chatClient.prompt()
                .user(message)
                .stream()
                .content();
        return output;
    }

    /**
     * chatModel的使用
     * @param message
     * @return
     */
    @GetMapping("/chat/model")
    @Operation(summary = "chatModel使用")
    public String chatModel(@RequestParam(value = "message",defaultValue = "给我讲个笑话")String message) {
        ChatResponse response = chatModel.call(
                new Prompt(
                        message, // 等同于new userMessage(message)
                        OpenAiChatOptions.builder()
                                .withModel("gpt-4-32k")  // 自定义大模型
                                .withTemperature(0.8F)  // 数值越大，回复越智能(0-1)
                                .build()
                ));
        return response.getResult().getOutput().getContent();
    }

    /**
     * 文生图
     * @param message
     * @return
     */
    @GetMapping("/text2Img")
    @Operation(summary = "文生图")
    public String text2Img(@RequestParam(value = "message",defaultValue = "画个猫")String message) {
        ImageResponse response = openAiImageModel.call(
                // 提示词
                new ImagePrompt(message,
                        OpenAiImageOptions.builder()
                                // 图片质量
                                .withQuality("hd")
                                // 生成图片数量
                                .withN(1)
                                // 使用大模型
                                .withModel(OpenAiImageApi.DEFAULT_IMAGE_MODEL)
                                // 高
                                .withHeight(1024)
                                // 宽
                                .withWidth(1024).build())

        );
        return response.getResult().getOutput().getUrl();
    }

    /**
     * 文生语音
     * @return
     */
    @GetMapping("/text2Audit")
    @Operation(summary = "文生语音")
    public String text2Audit() {
        // 文生语音配置
        OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
                // 模型
                .withModel(OpenAiAudioApi.TtsModel.TTS_1.value)
                // 语音
                .withVoice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY)
                // 文本格式
                .withResponseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
                .withSpeed(1.0f)
                .build();

        SpeechPrompt speechPrompt = new SpeechPrompt("Hello,大家好我是Koro", speechOptions);
        SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);
        byte[] body = response.getResult().getOutput();

        try {
            witeByteArrayToMp3(body,System.getProperty("user.dir"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "ok";
    }

    /**
     * 语音转文本
     * @return
     */
    @GetMapping("/audit2Text")
    @Operation(summary = "语音转文本")
    public String audit2Text() {
        var transcriptionOptions = OpenAiAudioTranscriptionOptions.builder()
                .withResponseFormat(OpenAiAudioApi.TranscriptResponseFormat.TEXT)
                .withTemperature(0f)
                .build();

        var audioFile = new ClassPathResource("/koro.mp3");
        AudioTranscriptionPrompt transcriptionRequest = new AudioTranscriptionPrompt(audioFile, transcriptionOptions);
        AudioTranscriptionResponse response = openAiAudioTranscriptionModel.call(transcriptionRequest);
        return response.getResult().getOutput();
    }

    private static void witeByteArrayToMp3(byte[] audidBytes, String outputFilePath) throws Exception {
        FileOutputStream fos = new FileOutputStream(outputFilePath + "/koro.mp3");
        fos.write(audidBytes);
        fos.close();
    }
}
